package gmu.swe.project.tracker;

import gmu.swe.project.io.ConfigFileParser;
import gmu.swe.project.peer.PeerInfo;
import gmu.swe.project.registry.KeepAliveServiceThread;
import gmu.swe.project.registry.RegistryInfo;
import gmu.swe.project.registry.RegistryUI;
import gmu.swe.project.registry.TrackerRegistration;
import gmu.swe.project.utils.Helper;

import java.net.ServerSocket;
import java.util.ArrayList;

/**
 * On startup the Tracker (server) should read the configuration file to find
 * the port number of the socket it should set up for Peer Registration and
 * Querying purposes. It should also read the IP addresses of the Registry
 * servers. It should then register itself as an available service. When a Peer
 * has sent information, it should add that information to its set of Peer Info.
 * It should respond to any query from either a Peer registered with it, or
 * other Trackers.
 * 
 * To start the server, the following arguments are needed: 
 * 3) interval time frame for the registry to check the tracker registration
 * 
 * In addition, a -DCONFIG_FILE_LOCATION java option must be provided to indicate 
 * where the config.xml file is (I think this will take care of the below concern)
 * 
 * ********Need to enforce a set location for the config file. ****** Current
 * design on the configuration file: <?xml version="1.0"?> <config> <!--IP
 * Address of this server - whatever kind it is -->
 * <ip_address>192.168.10.3</ip_address> <tracker> <!-- Port that the tracker
 * will listen on for Peers and Trackers -->
 * <listening_port>10398</listening_port> </tracker> <peer> <!-- Directory of
 * shared files --> <shared_file_directory>C:/Temp</shared_file_directory>
 * </peer> <!-- Registry servers --> <registries> <registry>
 * <svr_ip_address>192.168.10.2</svr_ip_address> <port>12345</port> </registry>
 * <registry> <svr_ip_address>192.168.10.3</svr_ip_address> <port>23456</port>
 * </registry> </registries> </config>
 * 
 * @author Christina Bradbury
 * @author
 * @author
 * @author
 * 
 */
public class Tracker extends Thread{

	// Store the information of all Peers registered with this Tracker
	static PeerRegistration peerRegistration = new PeerRegistration();
	// Store the list of other Trackers - retrieved from Registry
	static TrackerRegistration trackerRegistration = new TrackerRegistration();
	static ArrayList<RegistryInfo> registryServers = null;
	static TrackerInfo trackerInfo = new TrackerInfo();
	private static String intervalString = "";
	private static String config = "";
	private static TrackerUI tUI;
	Tracker(String interval, TrackerUI ui, String configArg)
	{
		intervalString = interval;
		tUI = ui;
		config = configArg; 
	}
	/**
	 * 
	 * 
	 * @param args
	 */
	public void run() {
		
		if(tUI != null)
			peerRegistration.setGUI(tUI);

		//temporary, take out later, before checking in
//		String trackerPortString = args[1];
//		int trackerPort = Integer.parseInt(trackerPortString);

		int interval = Integer.parseInt(intervalString);

		// get the information to send to the Registry servers
		trackerInfo = readConfigFile();
		// set initial workload to 0 - there are no connections on startup
		trackerInfo.setWorkload(new Integer(0));
		
		//Start keepAlivePing thread to continuously send pings to the registries,
		//the scheduled interval is provided by the command line argument
		tUI.print("Tracker::Register for the first time and start keepAlivePing thread");
		new KeepAlivePingThread(interval, registryServers).start();
		
		//Start keepAliveService thread to continuously check for Peers,
		//clears out the PeerRegistration if a Peer is no longer available
		tUI.print("Tracker::start KeepAliveService");
		new TrackerKeepAliveService(interval).start();

		boolean listening = true;
		try {
			ServerSocket serverSocket = new ServerSocket(trackerInfo
					.getListeningPort());
			while (listening) {
				tUI.print("Tracker listening...");
				new TrackerServiceThread(serverSocket.accept()).start();
			}
			serverSocket.close();
			tUI.print("Tracker server shut down");
		} catch (Exception e) {
			tUI.print(e.toString());
		}

	}// main
	
    
	/**
	 * Updates the trackerRegistration whenever a tracker sends an update or
	 * registers for the first time
	 */
	public static synchronized void updatePeerRegistration(PeerInfo peerInfo) {
		tUI.print("Tracker::updatePeerRegistration():update peer");
		peerInfo.setTimestamp(Helper.getCurrTime());
		peerRegistration.addPeer(peerInfo);
		trackerInfo.setWorkload(peerRegistration.peerSet.size());
		tUI.print("Tracker::updatePeerRegistration():peerRegistration size: "
				+ Integer.toString(peerRegistration.peerSet.size()));
	}// updateTrackerRegistration

	private static TrackerInfo readConfigFile() {

		TrackerInfo info = new TrackerInfo();

		// read the config file by getting the location from system property
		ConfigFileParser parser = new ConfigFileParser(config);

		// get the IP addresses of the Registry servers
		registryServers = parser.getRegistryServers();

		// get the port
		String registration = parser.getListeningPort();
		Integer listeningPort = Integer.valueOf(registration);
		info.setListeningPort(listeningPort);
		
		//uncomment the top and take this out before checking i
		//info.setListeningPort(port);

		// set the IP address
		info.setIpAddress(parser.getIpAddress());
 
		tUI.print("Tracker::readConfigFile:ip: " + info.getIpAddress());
		tUI.print("Tracker::readConfigFile:port: " + Integer.toString(info.getListeningPort()));
		return info;
	}

}
